#include "fxcc/core/graph/common/SkinnedMeshData.h"

using namespace fxcc::graph::common;

void fxcc::graph::common::SkinnedMeshData::Write(std::ofstream& ofs)
{
	Header header = GetHeader();
	ofs.write(reinterpret_cast<const char*>(&header), sizeof(header));

	if (!bones1s.empty())
		ofs.write(reinterpret_cast<const char*>(&bones1s[0]), sizeof(glm::ivec4) * bones1s.size());

	if (!weights1s.empty())
		ofs.write(reinterpret_cast<const char*>(&weights1s[0]), sizeof(glm::vec4) * weights1s.size());

	if (!bones2s.empty())
		ofs.write(reinterpret_cast<const char*>(&bones2s[0]), sizeof(glm::ivec4) * bones2s.size());

	if (!weights2s.empty())
		ofs.write(reinterpret_cast<const char*>(&weights2s[0]), sizeof(glm::vec4) * weights2s.size());
}

bool fxcc::graph::common::SkinnedMeshData::Read(std::ifstream& ifs)
{
	Header header;
	ifs.read(reinterpret_cast<char*>(&header), sizeof(header));

	if (header.version != CURRENT_VERSION)
	{
		std::cerr << "Unsupported version: " << header.version << ". Expected: " << CURRENT_VERSION << ".\n";
		return false;
	}

	//bones1s.resize(header.numBones1s);
	//weights1s.resize(header.numWeights1s);
	//bones2s.resize(header.numBones2s);
	//weights2s.resize(header.numWeights2s);

	ResizeHeader(header);

	if (!bones1s.empty())
		ifs.read(reinterpret_cast<char*>(&bones1s[0]), sizeof(glm::ivec4) * bones1s.size());

	if (!weights1s.empty())
		ifs.read(reinterpret_cast<char*>(&weights1s[0]), sizeof(glm::vec4) * weights1s.size());

	if (!bones2s.empty())
		ifs.read(reinterpret_cast<char*>(&bones2s[0]), sizeof(glm::ivec4) * bones2s.size());

	if (!weights2s.empty())
		ifs.read(reinterpret_cast<char*>(&weights2s[0]), sizeof(glm::vec4) * weights2s.size());

	return true;
}
void SkinnedMeshData::Resize(int numVertices)
{
	bones1s.resize(numVertices, glm::ivec4(-1));
	weights1s.resize(numVertices, glm::vec4(0.0f));
	bones2s.resize(numVertices, glm::ivec4(-1));
	weights2s.resize(numVertices, glm::vec4(0.0f));
}

bool SkinnedMeshData::AddBoneWeight(int vertexId, int boneId, float weightValue)
{
	glm::ivec4& aBones1 = bones1s[vertexId];
	glm::vec4& aWeights1 = weights1s[vertexId];
	glm::ivec4& aBones2 = bones2s[vertexId];
	glm::vec4& aWeights2 = weights2s[vertexId];

	for (int i = 0; i < 4; i++)
	{
		if (aWeights1[i] == 0.0f)
		{
			aWeights1[i] = weightValue;
			aBones1[i] = boneId;
			return true;
		}
	}

	for (int i = 0; i < 4; i++)
	{
		if (aWeights2[i] == 0.0f)
		{
			aWeights2[i] = weightValue;
			aBones2[i] = boneId;
			return true;
		}
	}
	return false;

}

void fxcc::graph::common::SkinnedMeshData::ResizeHeader(const Header& header)
{
	bones1s.resize(header.numBones1s);
	weights1s.resize(header.numWeights1s);
	bones2s.resize(header.numBones2s);
	weights2s.resize(header.numWeights2s);
}
